package com.licq.ldoc.writer.impl;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import com.licq.ldoc.writer.ElementWriter;
import com.licq.ldoc.writer.Writer;
import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Phrase;

public class DocWriter extends Writer {

	private static final String INITIALIZE_METHOD = "getInstance";
	
	private final String outputFileName;
	
	private DocFormat format;
	
	private List<ElementWriter> elementWriters = new ArrayList<ElementWriter>();

    public DocWriter(String fileName) {
    	this(fileName, DocFormat.from(StringUtils.substringAfterLast(
    			fileName, ".")));
    }
    
    public DocWriter(String fileName, DocFormat format) {
    	outputFileName = fileName;
    	this.format = format;
    	elementWriters.add(new StructureWriter());
    	elementWriters.add(new ExampleWriter());
    }

	public void write(List<com.licq.ldoc.domain.Element> elements) 
		throws FileNotFoundException, DocumentException {
		setCurrentFormat(format);
        Document document = new Document(PageSize.LETTER.rotate());
        initializeWriter(document);
        document.open();
        for (com.licq.ldoc.domain.Element element : elements) {
            writeElement(document, element);
        }
        document.close();
    }

	private void initializeWriter(Document document) throws FileNotFoundException {
		FileOutputStream fos = new FileOutputStream(outputFileName);
        try {
	        Class<? extends com.lowagie.text.DocWriter> writerClazz = getCurrentFormat().getWriterClazz();
	        Method method = writerClazz.getMethod(INITIALIZE_METHOD, Document.class, OutputStream.class);
	        method.invoke(null, document, fos);
        } catch (Exception e) {
        	throw new RuntimeException(e);
        }
	}

    private void writeElement(Document document, com.licq.ldoc.domain.Element element) 
    	throws DocumentException {
    	for (ElementWriter elementWriter : elementWriters) {
    		elementWriter.write(element, document);
    		writeIntervalSpace(document);
    	}
    }

	private void writeIntervalSpace(Document document) throws DocumentException {
		document.add(new Phrase(""));
		document.add(Chunk.NEWLINE);
	}

	public void setElementWriters(List<ElementWriter> elementWriters) {
		this.elementWriters = elementWriters;
	}
    
}

